Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update turf #91

Merged
merged 7 commits into from
Aug 20, 2024
Merged

update turf #91

merged 7 commits into from
Aug 20, 2024

Conversation

michaelkirk
Copy link
Collaborator

@michaelkirk michaelkirk commented Jul 29, 2024

This is a draft because it is based on #90, so please review that first.

Description

Taking a smaller bite out of #89, this PR only updates our turf dependency.

@michaelkirk michaelkirk marked this pull request as draft July 29, 2024 23:12
Comment on lines +130 to +131
guard let slicedLineBehind = LineString(coordinates.reversed()).sliced(from: closest.coordinate, to: coordinates.reversed().last) else { return nil }
guard let slicedLineInFront = nearByPolyline.sliced(from: closest.coordinate, to: coordinates.last) else { return nil }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was returning nil here not needed before?

Copy link
Collaborator Author

@michaelkirk michaelkirk Aug 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A good question!

The proximate answer is that the sliced method signature changed. Previously, if you had a LineString with 0 coordinates, if you tried to slice it, it would return another LineString with 0 coordinates. Now it returns nil.

Before:
mapbox/turf-swift@b05b465...v2.8.0#diff-809e6d4a01e9482c2a2ac457a5394236ec89bd5355c5ab09fddb69f686225aa2L175

public func sliced(from start: CLLocationCoordinate2D? = nil, to end: CLLocationCoordinate2D? = nil) -> LineString {
    // Ported from https://github.com/Turfjs/turf/blob/142e137ce0c758e2825a260ab32b24db0aa19439/packages/turf-line-slice/index.js
    guard !coordinates.isEmpty else {
        return LineString([])
    }
    ....

After:
mapbox/turf-swift@b05b465...v2.8.0#diff-9de11b3a56fd1de998fe9ec9a4b133b503af0298afe0008984076e5adb200ca9R276

public func sliced(from start: LocationCoordinate2D? = nil, to end: LocationCoordinate2D? = nil) -> LineString? {
    // Ported from https://github.com/Turfjs/turf/blob/142e137ce0c758e2825a260ab32b24db0aa19439/packages/turf-line-slice/index.js
    guard !coordinates.isEmpty else { return nil }

Seems a little arbitrary, but whatever. 🤷

In any case, could this conceivably affect behavior?

Well, a few lines below your comment is another line:

guard let pointBehind = slicedLineBehind.coordinateFromStart(distance: userDistanceBuffer) else { return nil }

This method in turn ultimately calls:

public func indexedCoordinateFromStart(distance: CLLocationDistance) -> IndexedCoordinate? {
    guard let firstCoordinate = coordinates.first else {
        return nil
    }
    ...
}

This is true for both the old and the new version of turf.

So to summarize, the difference only applies in the degenerate case of getting an empty LineString as input. And in that case, the only difference is we'd now return nil a few lines earlier than we would have returned nil before, but we'll still ultimately return nil.

Bottom line: I don't think there could be an observable change in behavior from this.

MapboxCoreNavigation/RouteProgress.swift Show resolved Hide resolved
@@ -1071,7 +1074,9 @@ open class NavigationMapView: MLNMapView, UIGestureRecognizerDelegate {
*/
@objc public func setOverheadCameraView(from userLocation: CLLocationCoordinate2D, along coordinates: [CLLocationCoordinate2D], for bounds: UIEdgeInsets) {
self.isAnimatingToOverheadMode = true
let slicedLine = Polyline(coordinates).sliced(from: userLocation).coordinates
guard let slicedLine = LineString(coordinates).sliced(from: userLocation)?.coordinates else {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In which cases does LineString.sliced return nil in this case?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same cause as my previous comment - sliced will now return nil rather than an empty LineString in the case that coordinates is empty.

The implications of this one are trickier though — it's possible that this might result in some change in behavior. My wager is that it's OK, since passing empty coordinates seems ill formed in the first place.

And in that case, our response is a no-op, rather than exploding or something scary.

I've just now added a debug assert to build confidence that we're not inadvertently hitting that code path.

What do you think?

@hactar
Copy link
Collaborator

hactar commented Aug 14, 2024

Looking fine, just have a few questions so that I fully understand the PR. Please resolve the merge conflict and mark as ready for review.

Previously the IndexedCoordinate returned from `closestPoint` had its
`distance` field set to the distance from the closest point on the Line.

But it was always intended to be distance from the `start` of the line.

Upstream fixed this in:
https://github.com/mapbox/turf-swift/pull/107/files

So this commit adapts to this new behavior.
Copy link
Collaborator Author

@michaelkirk michaelkirk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review - please take another look @hactar.

Comment on lines +130 to +131
guard let slicedLineBehind = LineString(coordinates.reversed()).sliced(from: closest.coordinate, to: coordinates.reversed().last) else { return nil }
guard let slicedLineInFront = nearByPolyline.sliced(from: closest.coordinate, to: coordinates.last) else { return nil }
Copy link
Collaborator Author

@michaelkirk michaelkirk Aug 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A good question!

The proximate answer is that the sliced method signature changed. Previously, if you had a LineString with 0 coordinates, if you tried to slice it, it would return another LineString with 0 coordinates. Now it returns nil.

Before:
mapbox/turf-swift@b05b465...v2.8.0#diff-809e6d4a01e9482c2a2ac457a5394236ec89bd5355c5ab09fddb69f686225aa2L175

public func sliced(from start: CLLocationCoordinate2D? = nil, to end: CLLocationCoordinate2D? = nil) -> LineString {
    // Ported from https://github.com/Turfjs/turf/blob/142e137ce0c758e2825a260ab32b24db0aa19439/packages/turf-line-slice/index.js
    guard !coordinates.isEmpty else {
        return LineString([])
    }
    ....

After:
mapbox/turf-swift@b05b465...v2.8.0#diff-9de11b3a56fd1de998fe9ec9a4b133b503af0298afe0008984076e5adb200ca9R276

public func sliced(from start: LocationCoordinate2D? = nil, to end: LocationCoordinate2D? = nil) -> LineString? {
    // Ported from https://github.com/Turfjs/turf/blob/142e137ce0c758e2825a260ab32b24db0aa19439/packages/turf-line-slice/index.js
    guard !coordinates.isEmpty else { return nil }

Seems a little arbitrary, but whatever. 🤷

In any case, could this conceivably affect behavior?

Well, a few lines below your comment is another line:

guard let pointBehind = slicedLineBehind.coordinateFromStart(distance: userDistanceBuffer) else { return nil }

This method in turn ultimately calls:

public func indexedCoordinateFromStart(distance: CLLocationDistance) -> IndexedCoordinate? {
    guard let firstCoordinate = coordinates.first else {
        return nil
    }
    ...
}

This is true for both the old and the new version of turf.

So to summarize, the difference only applies in the degenerate case of getting an empty LineString as input. And in that case, the only difference is we'd now return nil a few lines earlier than we would have returned nil before, but we'll still ultimately return nil.

Bottom line: I don't think there could be an observable change in behavior from this.

MapboxCoreNavigation/RouteProgress.swift Show resolved Hide resolved
@@ -1071,7 +1074,9 @@ open class NavigationMapView: MLNMapView, UIGestureRecognizerDelegate {
*/
@objc public func setOverheadCameraView(from userLocation: CLLocationCoordinate2D, along coordinates: [CLLocationCoordinate2D], for bounds: UIEdgeInsets) {
self.isAnimatingToOverheadMode = true
let slicedLine = Polyline(coordinates).sliced(from: userLocation).coordinates
guard let slicedLine = LineString(coordinates).sliced(from: userLocation)?.coordinates else {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same cause as my previous comment - sliced will now return nil rather than an empty LineString in the case that coordinates is empty.

The implications of this one are trickier though — it's possible that this might result in some change in behavior. My wager is that it's OK, since passing empty coordinates seems ill formed in the first place.

And in that case, our response is a no-op, rather than exploding or something scary.

I've just now added a debug assert to build confidence that we're not inadvertently hitting that code path.

What do you think?

@michaelkirk michaelkirk marked this pull request as ready for review August 15, 2024 22:45
Copy link
Collaborator

@hactar hactar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your comments and improvements. Sounds all reasonable to me. Approving. Will merge a day later in case someone else wishes to take a look too in the mean time.

@michaelkirk michaelkirk merged commit e4dfc50 into maplibre:main Aug 20, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants